#!/usr/bin/env python

import sys
import os
import time
import pygame
import pygame.camera
from pygame.locals import *
from PIL import Image
from ctypes import windll

# Dimensions of the video
vwidth	= 1280
vheight	= 720
vsize		= (vwidth,vheight)

# Show the video scaled to full screen?
# Note: This will stretch aspect ratio if it is different than the screen resolution.
full_screen = True

# How many photos should be taken for the strip?
strip_size = 3

# How many pixels thick should the border be?
border_thickness = 35

# How many seconds between pictures?
countdown_timer = 5

# Should we send the strip to the printer?
print_strip = False

# Background image to be use.
bg_image = "backgrounds\\film-border-4x6_v2_canvas.png"

# Full path to IrfanView
irfanview_path = "C:\Program Files (x86)\IrfanView\i_view32.exe"

# Setup some Windows stuff to keep the window always on top.
SetWindowPos = windll.user32.SetWindowPos
screen_x = windll.user32.GetSystemMetrics(0)
screen_y = windll.user32.GetSystemMetrics(1)
screen_resolution = (screen_x, screen_y)

# Setup some pygame variables for capturing video.
screen  = pygame.display.set_mode(screen_resolution, pygame.NOFRAME)
surface = pygame.surface.Surface(vsize,0,screen)
screen_position = ((screen_x - vwidth) / 2, (screen_y - vheight) / 2)

# Finish window setup and hide the mouse arrow
SetWindowPos(pygame.display.get_wm_info()['window'], -1, 0, 0, 0, 0, 0x0001)
pygame.mouse.set_visible(False)

# Temporary Photos
tmp_pic = []

# Sounds
pygame.mixer.init(11025, 16, 1, 256)
snd_beep = pygame.mixer.Sound("sounds\\beep.wav")
snd_snap = pygame.mixer.Sound("sounds\\camera-snap.wav")

# Choose which camera to use and start it.
pygame.init()
pygame.camera.init()
cam = pygame.camera.Camera(pygame.camera.list_cameras()[0], vsize)
cam.start()

# Take a picture and save it as a variable.
def take_picture(surface):
	snd_snap.play()
	image = cam.get_image(surface)
	data = []
	for y in range(0, image.get_height()):
        	row = []
        	for x in range(0, image.get_width()):
        		r,g,b,a = image.get_at((x,y))
        		row.append( (r,g,b) )
        	data.append(row)
	return convert_image(data)
	
# Convert pygame camera image to PIL image
def convert_image(data):
	im = Image.new('RGB', vsize)
	masheddata = []
	for row in data:
		masheddata += row
	im.putdata(masheddata)
	
	return im

# Save a picture to disk.
def save_picture(filename, im):
	im.save(filename, quality=95)
	
# Generate the photo strip
def generate_strip(pics):
	# Calculate the size of the new image
	no_pics = len(pics)
	#strip_size = (vwidth + (border_thickness * 2), (no_pics * vheight) + (border_thickness * (no_pics + 1)))
	
	# Create the new image
	#strip = Image.new('RGB', strip_size)
	strip = Image.open(bg_image)
	
	upper_x = (strip.size[0] - vwidth) / 2
	lower_x = upper_x + vwidth
	
	border_size = (strip.size[1] - (no_pics * vheight)) / (no_pics + 1)
	
	# Loop through all of the pictures and paste them on the new image
	for i in range(no_pics):
		# Determine the x-y coordinates for the top left and bottom right
		upper_y = (border_size * (i +1)) + (i * vheight)
		lower_y = upper_y + vheight
		box =  (upper_x, upper_y,  lower_x, lower_y)
		
		# Add picture to image
		strip.paste(pics[i], box)
	
	# Return the strip
	return strip

# Countdown n seconds while showing the current feed.
def countdown(timer):
	start_time = time.time() 
	current_time = time.time()
	last_time = None
	
	# Overlay the countdwn seconds over the video feed.
	while start_time + timer > current_time:
		time_left = int((timer + 1)- (current_time - start_time))
		
		# Play sound if number has changed
		if last_time != time_left:
			snd_beep.play()
			last_time = time_left
			
		show_video(str(time_left))
		current_time = time.time()
		
# Loop through video captures to create the illusion of streaming video.
def show_video(display_text = None):
	# Get the current image.
	image = cam.get_image(surface)
	
	# Write something to the screen
	font = pygame.font.Font(None, 72)
	font.set_bold(True)
	text = font.render(display_text, 1, (255, 0, 0))
	textpos = text.get_rect(centerx=screen.get_width()/2, centery=screen.get_height()/2)
	
	
	# Display the current image flipped in the window.
	if full_screen:
		screen.blit(pygame.transform.scale(pygame.transform.flip(image, 1, 0), screen_resolution), (0,0))
	else:
		screen.blit(pygame.transform.flip(image, 1, 0),screen_position)
		
	screen.blit(text, textpos)
	pygame.display.update()
	
# Wait x number of seconds while showing live video
def video_wait(seconds, display_text = None):
	wait_time = time.time() + seconds
	while time.time() < wait_time:
		show_video(display_text)
		
# Display the photo strip on the screen for x number of seconds
def display_strip(seconds, strip):
	# Load the image and scale it to fit the screen
	image = pygame.transform.scale(pygame.image.load(strip), (screen_x/strip_size, screen_y))
	x_pos = (screen_x -image.get_width()) / 2
	
	# Create a blank surface
	surface = pygame.surface.Surface(screen_resolution,0,screen)
	surface.fill(pygame.Color("white"))
	screen.blit(surface, (0,0))

	# Display the photo strip
	screen.blit(image, (x_pos,0))
	pygame.display.update()
	
	# Keep the strip displayed for x seconds
	wait_time = time.time() + seconds
	while time.time() < wait_time:
		pass
		
	# Reset the black background
	surface.fill(pygame.Color("black"))
	screen.blit(surface, (0,0))

# Main loop of the program
while 1:
	show_video("Press the Easy Button to begin")

	# Look for keyboard events that are asking to do something.
	for event in pygame.event.get():
	
		# Take a snapshot and save it.
		if event.type == pygame.KEYDOWN:
			if event.key == pygame.K_SPACE:
				for pic in range(1, strip_size + 1):
					countdown(countdown_timer)
					video_wait(1)
					snap_image = take_picture(surface)
					tmp_pic.append(snap_image)
					
				# Get the current epoch time
				epoch = str(int(time.time()))
				
				# Save each individual picture
				for pic in range(strip_size):
					pic_name = "strips\\"  + epoch + "_" + str(pic) + ".jpg"
					save_picture(pic_name, tmp_pic[pic])
			
				# Create the photostrip image and print it
				strip_name = "strips\\" + epoch + ".jpg"
				strip = generate_strip(tmp_pic)
				save_picture(strip_name, strip)
				
				# Clear the current pics
				del tmp_pic[:]
				
				# Display video while the strip is being saved
				video_wait(3, "Developing photo strip. Please wait.")
				
				# Send the strip to the printer
				if print_strip:
					script_dir = os.path.dirname(os.path.realpath(__file__))
					os.system("\"" + irfanview_path + "\" " + script_dir + "\\" + strip_name + " /print")
					
				# Display photo strip
				display_strip(10, strip_name)

				# Clear the event queue in case the button was pressed multiple times
				pygame.event.clear()
			elif event.key == pygame.K_ESCAPE:
				sys.exit()
			
		# Quit
		if event.type == pygame.QUIT:
			sys.exit()
